# __init__文件

# __init__​文件

  • Python3的包目录下会有一个__init__.py​文件,其目的是在import package​时自动执行一些内容-初始化
  • 若包中还有子包,并且都有__init__.py​​文件,执行顺序为从外到里(记住这个文件的目的是导入包时自动进行初始化)
  • 当没有__init__.py​文件时会有些不同,不是仅仅当默认存在一个空的__init__​文件,而是创建了一个所谓的命名空间包。

# __all__

  • 可以在__init__.py​文件中使用__all__​控制import想要暴露出去的内容

  • 使用from ... import *​ 的方式将会将一个模块的全部不以_​开头的内容导入到当前的命名空间,但这种方式不应该被过多使用-容易造成命名冲突。

  • python会进入文件系统,找到这个包所有的子模块并一一导入

    • 在大小写不区分的平台上(例如windows)会导致问题

      • 例如无法确定ECHO.py导入为模块echo还是Echo还是ECHO
    • 可以在init.py中系统一个__all__​的列表变量,在使用import * 时将列表中的所有名字作为包内容导入

      __all__ = ["echo", "surround", "reverse"]
      
  • 若没有__all__​则是暴露所有可以暴露的

# import

可以在__init__.py​中加载子模块用于做到在加载模块时自动加载子模块,此用法也常用于将多个文件合并为一个逻辑命名空间。

# graphics/formats/__init__.py
from . import jpg
from . import png

# 命名空间包

有两个目录存在相同的命名空间spam,但任何一个目录中都没有__init__.py​文件

foo-package/
    spam/
        blah.py

bar-package/
    spam/
        grok.py

可以通过都将其路径加入sys.path​中实现一个命名空间包-解释器创建了一个由所有包含匹配包名的目录组成的列表,通过这样的方式允许人们能够轻松地为这样的框架编写第三方附加组件和其他扩展。

>>> import sys
>>> sys.path.extend(['foo-package', 'bar-package'])
>>> import spam.blah
>>> import spam.grok
>>> import spam
>>> spam.__path__
_NamespacePath(['foo-package/spam', 'bar-package/spam'])
>>>